package com.briup.jd2407cms.service.impl;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.briup.jd2407cms.aop.Logging;
import com.briup.jd2407cms.domain.Article;
import com.briup.jd2407cms.domain.Category;
import com.briup.jd2407cms.domain.extend.CategoryExtend;
import com.briup.jd2407cms.exception.ServiceException;
import com.briup.jd2407cms.mapper.ArticleMapper;
import com.briup.jd2407cms.service.CategoryService;
import com.briup.jd2407cms.mapper.CategoryMapper;
import com.briup.jd2407cms.util.result.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author jay
 * @description 针对表【cms_category】的数据库操作Service实现
 * @createDate 2024-11-18 14:40:14
 */
@Slf4j
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category>
        implements CategoryService {
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private ArticleMapper articleMapper;

    //查询得到所有的一级栏目（含二级）
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public List<CategoryExtend> selectAllParent() {
        List<CategoryExtend> list = categoryMapper.selectAllWithParent();
        if (list == null || list.isEmpty())
            throw new ServiceException(ResultCode.CATEGORY_NOT_EXIST);
        return list;
    }

    @Override
    public List<CategoryExtend> selectAllWithChild() {
        List<CategoryExtend> allWithChild = categoryMapper.selectAllWithChild();
        if (ObjUtil.isEmpty(allWithChild)){
            throw new ServiceException(ResultCode.CATEGORY_NOT_EXIST);
        }
        return allWithChild;
    }

    @Logging("分页查询所有栏目")
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public IPage<Category> page(Integer pageNum, Integer pageSize, Integer parentId) {
        Page<Category> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Category> lqw =
                new LambdaQueryWrapper<Category>().eq(parentId != null, Category::getParentId, parentId)
                        .orderByAsc(Category::getParentId)
                        .orderByAsc(Category::getOrderNum);
        return categoryMapper.selectPage(page, lqw);
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public boolean save(Category category) {
        // 判断 category==null【可不写，前端会处理】
        if (category == null) {
            log.error("新增的栏目为空");
            throw new ServiceException(ResultCode.PARAM_IS_BLANK);
        }

        // 1.判断 栏目名是否唯一
        LambdaQueryWrapper<Category> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Category::getName, category.getName());
        Integer i = categoryMapper.selectCount(lqw);
        if (i != 0) {
            log.error("栏目名已存在");
            throw new ServiceException(ResultCode.CATEGORYNAME_HAS_EXISTED);
        }

        // 2.如果包含父栏目，则判断parentId是否有效
        Integer parentId = category.getParentId();
        Category parentCategory = categoryMapper.selectById(parentId);
        // cgx:
        /* if (parentId == null) {
            log.error("新增栏目时，传入的parentId为空");
            throw new ServiceException(ResultCode.PCATEGORY_IS_INVALID);
        } else */
        if (parentId != null && parentCategory == null) {
            log.error("栏目携带的父栏目无效");
            throw new ServiceException(ResultCode.PARAM_IS_INVALID);
        }

        // 3.获取max(order_num)
        // 栏目表中无数据，新插入栏目序号为1
        category.setOrderNum(1);
        // 栏目表中有数据，新插入栏目序号 = max(order_num) + 1;
        if (categoryMapper.selectCount(null) != 0) {
            // 获取当前最大权重
            Integer maxOrderNum = categoryMapper.selectMaxOrderNum();
            log.info("栏目表中有数据，最大的栏目序号为：{}", maxOrderNum);
            // cgx:判断当前最大值是不是10，如果是，只能放10，如果不是，请+1
            /* if (maxOrderNum == 10) {
                category.setOrderNum(10);
            } else if (maxOrderNum < 10) {
                category.setOrderNum(maxOrderNum + 1);
            }else {
                // 抛个异常
                log.error("category权重数字不符合要求，请检查！");
                throw new ServiceException(ResultCode.DATA_WRONG);
            }*/
            maxOrderNum += 1;
            log.info("新插入栏目序号为：" + maxOrderNum);
            //4.设置order_num值
            category.setOrderNum(maxOrderNum);
        }

        // 5、插入
        return super.save(category);
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public boolean updateById(Category category) {
        // 1.id判断：不能为空 必须有效
        Integer id = category.getId();
        Category ocategory = categoryMapper.selectById(id);
        if (id == null || ocategory == null) {
            log.error("要修改的栏目不存在！");
            throw new ServiceException(ResultCode.CATEGORY_NOT_EXIST);
        }

        // 2.name判断：如果存在则必须唯一
        String name = category.getName();
        if (!StrUtil.isEmpty(name) && !ocategory.getName().equals(name)) {
            Integer count = categoryMapper.selectCount(
                    new LambdaQueryWrapper<Category>()
                            .eq(Category::getName, name)
            );
            if (count != 0) {
                log.error("新修改的栏目名称已存在");
                throw new ServiceException(ResultCode.CATEGORYNAME_HAS_EXISTED);
            }
        }

        // 3.如果当前栏目为1级，则不能更改为2级
        Integer parentId = category.getParentId();
        if (parentId != null && ocategory.getParentId() == null) {
            log.error("当前栏目为1级，不能更改为2级");
            throw new ServiceException(ResultCode.CATEGORY_LEVEL_SETTING_ERROR);
        }
        //4.如果需要修改的栏目为2级，?且要修改其父栏目？
        else if (parentId != null) {
            // 需要更新的父栏目不存在，或 ？需要更新的父栏目为2级栏目？，则失败
            if (categoryMapper.selectById(parentId) == null)
                throw new ServiceException(ResultCode.PCATEGORY_IS_INVALID);
        }
        return super.updateById(category);
    }

    @Override
    public void removeCategoryById(String id){
        // 如果是一级栏目，验证下面是否有二级栏目
        // 如果有，则不能删除 => id 作为parentId查询能得到结果，就不能删
        LambdaQueryWrapper<Category> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Category::getParentId, id);
        // select count
        Integer childCount = categoryMapper.selectCount(lqw); // 一级栏目下子栏目的个数
        if (childCount != null && childCount != 0){
            log.error("要删除的父栏目下存在子栏目，无法删除");
            throw new ServiceException(ResultCode.PARAM_IS_INVALID);
        }

        // 如果是二级栏目，需要检查
        // 1、该栏目下是否有绑定文章，如果没有则可以删除，如果有继续判断
        List<Article> articles = articleMapper.selectList(new LambdaQueryWrapper<Article>().eq(Article::getCategoryId, id));
        if (articles != null && !articles.isEmpty()){
            // 2、如果该栏目下有绑定的文章，判断该文章作者是否处于账号注销状态，如果不是则无法删除
            // 只有这些文章所属用户的账号状态都为注销的情况下，才可以删除
            // 根据文章id 查询 用户 =>
            // 遍历所有用户的账号状态
            List<String> userStatus = articleMapper.selectUserStatusByArticleIds(
                    articles.stream()
                    .map(Article::getId)
                    .collect(Collectors.toList()));
            if (userStatus.contains("启用")){
                log.error("该类别下的文章所属的用户依然有效，不可删除类别");
                throw new ServiceException(ResultCode.FAIL);
            }
        }
        // 其余情况，正常删除
        removeById(id);
    }
    @Override
    public void removeCategoryBatch(List<String> ids){
        // 简单实现
        for (String id : ids) {
            removeCategoryById(id);
        }
    }

    // 查询得到所有的一级栏目, 不含二级栏目 ,用于导入时转换名称和ID
    @Override
    public List<Category> queryAllOneLevel() {
        LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.isNull(Category::getParentId);
        List<Category> list = categoryMapper.selectList(queryWrapper);
        if (ObjUtil.isEmpty(list)){
            log.error("导入时，查询得到所有的一级栏目为空");
            throw new ServiceException(ResultCode.CATEGORY_NOT_EXIST);
        }
        return list;
    }

    @Override
    @Transactional
    public void insertBatch(List<Category> categories) {
        // 简单法：1，适用于有逻辑的新增，name的唯一性，orderNum的自增
        for (Category category : categories) {
            this.save(category);
        }
        // 简单法：2，适用于没有任何逻辑的新增
//        super.saveBatch(categories);

    }

    @Override
    public List<Category> getAll() {
        LambdaQueryWrapper<Category> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Category::getDeleted, "1");
        return categoryMapper.selectList(null);
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public boolean removeByIds(Collection<? extends Serializable> ids) {
        try {
            List<Category> dCategories = categoryMapper.selectBatchIds(ids);
            HashSet<Category> categoryHashSet = new HashSet<>(dCategories);
//            ids.forEach((id) -> {
            for (Serializable id : ids) {
                //1.栏目id判断
                Category category = categoryMapper.selectById(id);
                if (category == null) {
                    log.error("要删除的栏目不存在");
                    throw new ServiceException(ResultCode.CATEGORY_NOT_EXIST);
                }
                //2.栏目级别判断
                if (category.getParentId() == null) {
                    // 2.1 如果该1级栏目下存在2级栏目，删除失败
                    List<Category> categories = categoryMapper.selectByParentId(category.getId());
                    if (!ObjUtil.isEmpty(categories) && !categoryHashSet.containsAll(categories)) {
                        log.error("该1级栏目下存在2级栏目，删除失败 categoryId={}", id);
                        throw new ServiceException(ResultCode.PARAM_IS_INVALID);
                    }
                } else {
                    // 二级栏目
                    // 2.2 如果2级栏目下不存在任何资讯，可以删除成功
                    if (articleMapper.selectCount(
                            new LambdaQueryWrapper<Article>()
                                    .eq(Article::getCategoryId, id)) != 0) {
                        log.error("下级栏目下存在资讯，删除失败 categoryId={}", id);
                        throw new ServiceException(ResultCode.PARAM_IS_INVALID);
                    }
                    // 2.3 如果2级栏目下存在3级目录，删除失败
                    List<Category> categories = categoryMapper.selectByParentId(category.getId());
                    if (!ObjUtil.isEmpty(categories) && !categoryHashSet.containsAll(categories)) {
                        log.error("2级栏目下存在3级目录，删除失败 categoryId={}", id);
                        throw new ServiceException(ResultCode.PARAM_IS_INVALID);
                    }
                    // 3.栏目删除
                    super.removeById(id);
                }
            }
//            });
        } catch (Throwable throwable){
            log.error("删除栏目时发生异常", throwable);
            return false;
        }
        return true;
    }


    // -------- 私有工具 --------
//    private void deleteNonParentCategory(){
//        List<Category> dcategories = categoryMapper.selectBatchIds(ids);
//        HashSet<Category> categoryHashSet = new HashSet<>(dcategories);
//        Integer count = 2;
//        // 二级栏目
//        // 2.2 如果2级栏目下不存在任何资讯，可以删除成功
//        LambdaQueryWrapper<Article> lqw = new LambdaQueryWrapper<Article>().eq(Article::getCategoryId, id);
//        Article article = articleMapper.selectOne(lqw);
//        if (!ObjUtil.isEmpty(article)){
//            log.error("{}级栏目下存在资讯，删除失败 categoryId={}",count,id);
//            throw new ServiceException(ResultCode.PARAM_IS_INVALID);
//        }
//        // 2.3 如果2级栏目下存在3级目录，删除失败
//        List<Category> categories = categoryMapper.selectByParentId(category.getId());
//        if (!ObjUtil.isEmpty(categories) && !categoryHashSet.containsAll(categories)){
//            log.error("{}级栏目下存在{}级目录，删除失败 categoryId={}", count, count + 1, id);
//            throw new ServiceException(ResultCode.PARAM_IS_INVALID);
//        }
//    }

    private boolean checkCategoryName(String categoryName){
        // 判读栏目名称是否重复
        LambdaQueryWrapper<Category> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Category::getName,categoryName);
        // c代表根据加入的名字查出来的栏目对象
        Category c = categoryMapper.selectOne(lqw);
        // 如果c不为空，则证明名称不唯一
        return !Objects.nonNull(c);
    }

//    @Override
//    public void modifyCategory(Category category) {
//
//        // 修改栏目名称的话，保证唯一性
//        String categoryName = category.getName();
//        Integer categoryId = category.getId();
//        // 根据id查询category的对象
//        Category oldCategory = getByCategoryId(categoryId);
//        if(StringUtils.hasText(categoryName)) {
//            // 验证和之前的一样不一样
//            if(categoryName.equals(oldCategory.getName())){
//                log.error("不能修改和之前一样的类别名字");
//                throw new ServiceException(ResultCode.FAIL);
//            }else {
//                // 判读栏目名称是否重复
//                if(!checkCategoryName(categoryName)){
//                    log.error("新增栏目时，栏目名称重复");
//                    throw new ServiceException(ResultCode.DATA_NOT_UNIQUE);
//                }
//            }
//        }
//
//        // 栏目级别不可以修改 => parentId不能由有数据置为null，不能由null变为具体数字
//
//        // 可以更改二级栏目的所属一级栏目
//        // 检查原来的parentId是多少
//        Integer oldParentId = oldCategory.getParentId();
//        // 比对传入的和原来的是否一致，要求传入的和原来的parentId都得有值
//        if(oldParentId == null || oldParentId.equals(category.getParentId())){
//            category.setParentId(null);
//        }
//        updateById(category);
//    }

}




